// // 处理开发时的SSR渲染情况
// const path = require('path')
// const Router = require('koa-router')
// const axios = require('axios')
// const MemoryFS = require('memory-fs')
// const fs = require('fs')
// const webpack = require('webpack')
// const VueServerRenderer = require('vue-server-renderer')
// const serverRender = require('./server-render')

// const serverConfig = require('../../build/webpack.config.server')

// // 1 编译webpack,让webpack跑起来
// // serverCompiler可以直接在nodejs中run 或 watch
// // 然后可以帮我们生成一个在服务端渲染时要用的一个bundle
// const serverCompiler = webpack(serverConfig)

// // MemoryFS与nodejs 中的fs一样，而且又扩展了一些API
// // 与fs唯一的区别是不把文件写到磁盘上面，而是直接写到内存里面
// // 写入磁盘是一个浪费时间的且效率低下，因为webpack去编译文件、读取文件、输出
// // 文件如果都是从磁盘上操作那整个的效率主比较低，因为webpack依赖的文件会非常多
// const mfs = new MemoryFS()
// // 所以这里把webpack的输出都放在memoryfs中，这样文件操作就非常快
// serverCompiler.outputFileSystem = mfs

// // bundle 用户记录webpack每次打包生成的新文件
// let bundle
// // watch好处是跟webpack-dev-server一样，在cilent目录下面，每次改了某一个文件
// // 它都会重新执行一个打包，重新执行打包后就可以拿到新的文件了
// // params:{} 默认空
// // params:() 回调函数
// serverCompiler.watch({}, (err, stats) => {
//   if (err) throw err // 打包出错，直接抛出
//   // eslint出错不会在err中出现，
//   stats = stats.toJson()
//   // 非webpack的错误会在stats中发现
//   stats.errors.forEach(err => console.log(err))
//   stats.warnings.forEach(warn => console.log(warn))

//   const bundlePath = path.join(
//     serverConfig.output.path,
//     'vue-ssr-server-bundle.json'
//   )
//   // 读取打包好的文件
//   bundle = JSON.parse(mfs.readFileSync(bundlePath, 'utf-8'))
//   console.log('new bundle generatered')
// })

// const handleSSR = async (ctx) => {
//   if (!bundle) { // 判断打包好的bundle文件是否存在
//     ctx.body = '请稍后 ... ...'
//     return
//   }

//   const clientManifestResp = await axios.get(
//     'http://127.0.0.1:8000/public/vue-ssr-client-manifest.json'
//     // vue-ssr-client-manifest.json  这个文件是哪来的呢?
//     // 需要通过插件()在 webpack-dev-server(在webpack-config.client.js)中生成这个文件，
//     // 当然这个插件是需要提前在webpack-dev-server中加入,详情见webpack-config.client.js中第 7 行和第 20 行配置,会乱当前的参数文件名
//   )
//   const clientManifest = clientManifestResp.data // 拿到axios返回的数据

//   // 拿到模板文件 ejs
//   const template = fs.readFileSync(
//     path.join(__dirname, '../server.template.ejs'),
//     'utf-8'
//   )
//   // 声明 render
//   const renderer = VueServerRenderer
//     .createBundleRenderer(bundle, {
//       inject: false, // 不会执行注入操作，只要把app string 渲染出来，自己处理剩下的内容就行了
//       clientManifest
//     })
//   // 最后一步操作，获取客户端 webpack-dev-server帮我们打包出来的js文件的一个地址
//   // 因为要拿到这个地址后才能去拼接HTML的时候去把这个客户端的JS路径写在HTML里面
//   // 这样的话我们把HTML返回给浏览器渲染内容时可以引用到这个JS文件，这样整个应用在浏览器中可以跑起来
//   // 不然只有HTML内容，却没有JS的逻辑交互效果
//   // 那这部分内容怎么拿到呢，因为dev-ssr是一个单独的运行在node上的server,而webpack-dev-serv又是一个单独的server
//   // 解决方案是通过axios向webpack-dev-server发送一个请求，拿到这个文件见第 53 行代码
//   await serverRender(ctx, renderer, template)
// }

// const router = new Router()
// router.get('*', handleSSR)
// module.exports = router

const Router = require('koa-router')
const axios = require('axios')
const path = require('path')
const fs = require('fs')
const MemoryFS = require('memory-fs')
const webpack = require('webpack')
const VueServerRenderer = require('vue-server-renderer')

const serverRender = require('./server-render')
const serverConfig = require('../../build/webpack.config.server')

const serverCompiler = webpack(serverConfig)
const mfs = new MemoryFS()
serverCompiler.outputFileSystem = mfs

let bundle
serverCompiler.watch({}, (err, stats) => {
  if (err) throw err
  stats = stats.toJson()
  stats.errors.forEach(err => console.log(err))
  stats.warnings.forEach(warn => console.warn(err))

  const bundlePath = path.join(
    serverConfig.output.path,
    'vue-ssr-server-bundle.json'
  )
  bundle = JSON.parse(mfs.readFileSync(bundlePath, 'utf-8'))
  console.log('new bundle generated')
})

const handleSSR = async (ctx) => {
  if (!bundle) {
    ctx.body = '你等一会，别着急......'
    return
  }

  const clientManifestResp = await axios.get(
    'http://127.0.0.1:8000/public/vue-ssr-client-manifest.json'
  )
  const clientManifest = clientManifestResp.data

  const template = fs.readFileSync(
    path.join(__dirname, '../server.template.ejs'),
    'utf-8'
  )

  const renderer = VueServerRenderer
    .createBundleRenderer(bundle, {
      inject: false,
      clientManifest
    })

  await serverRender(ctx, renderer, template)
}

const router = new Router()
router.get('*', handleSSR)

module.exports = router
